#ifndef LINK_LIST_H
#define LINK_LIST_H

#include <stdint.h>
#include <stdbool.h>

//链表节点
typedef struct Link_s 
{
	struct Link_s *prev;    //上一个节点
	struct Link_s *next;    //下一个节点
} LIST_NODE;

//链表管理器
typedef struct  {	
	LIST_NODE *head;        //链表头
	LIST_NODE *tail;        //链表尾
	uint32_t count;         //数据个数
} LIST_MANAGE;

//函数状态返回
typedef enum {
	L_OK = 0,	//操作成功
	L_EMPTY,    //链表为空
	L_REPEAT,	//操作失败，节点重复
	L_NOTHAVE,  //操作失败，原节点不在链表里边
	L_OUTINDEX, //操作失败，索引不在链表里边
	L_ERROR		//操作失败，其他原因
} LIST_RETURN;

/******************************************************************************
 *函数名称：  container_of
 *输入参数：  ptr，结构体某个某个成员的指针
 *			 type，结构体名字
 * 			 member，ptr对应的结构体成员的名字 
 *			 注意：type和member即不是变量也不是字符串，只是个名字，
 *					因此既不能传入变量，也不能用双引号 
 *输出参数：  无 
 *返回值  ：  根据输入的成员指针返回结构体的指针 
 *功能描述：  根据输入的成员指针返回结构体的指针 
 ******************************************************************************/
#ifndef container_of
	#define container_of(ptr, type, member) \
	((type *)((size_t)ptr - (size_t)(&(((type *)0)->member))))	
#endif
/******************************************************************************
 *函数名称：  ListManageInit
 *输入参数：  listManage,链表管理器地址
 *输出参数：  无
 *返回值  ：  无
 *功能描述：  初始化链表管理器，此管理器一定是用户声明的变量
 ******************************************************************************/
void ListManageInit(LIST_MANAGE *listManage);

/******************************************************************************
 *函数名称：  ListLength
 *输入参数：  listManage,链表管理器地址
 *输出参数：  无
 *返回值  ：  链表数据个数
 *功能描述：  获取链表数据的个数
 ******************************************************************************/
uint32_t ListLength(const LIST_MANAGE *listManage);


/******************************************************************************
 *函数名称：  ListPeekHead
 *输入参数：  listManage,链表管理器地址
 *输出参数：  readNode,获取的节点地址
 *返回值  ：  获取成败信息
 *功能描述：  获取首节点地址
 ******************************************************************************/
LIST_RETURN ListPeekHead(const LIST_MANAGE *listManage, LIST_NODE **readNode);
void * vListPeekHead(const LIST_MANAGE *listManage);

/******************************************************************************
 *函数名称：  ListPeekTail
 *输入参数：  listManage,链表管理器地址
 *输出参数：  readNode,获取的节点地址
 *返回值  ：  获取成败信息
 *功能描述：  获取尾节点地址
 ******************************************************************************/
LIST_RETURN ListPeekTail(const LIST_MANAGE *listManage, LIST_NODE **readNode);
void * vListPeekTail(const LIST_MANAGE *listManage);

/******************************************************************************
 *函数名称：  ListPeekNext
 *输入参数：  listNode,已知节点
 *输出参数：  readNode,获取的节点地址
 *返回值  ：  获取成败信息
 *功能描述：  获取已知节点的下一个节点
 ******************************************************************************/
LIST_RETURN ListPeekNext(const LIST_NODE *listNode, LIST_NODE **readNode);
void * vListPeekNext(const LIST_NODE *listNode);

/******************************************************************************
 *函数名称：  ListPeekPrev
 *输入参数：  listNode,已知节点
 *输出参数：  readNode,获取的节点地址
 *返回值  ：  获取成败信息
 *功能描述：  获取已知节点的上一个节点
 ******************************************************************************/
LIST_RETURN ListPeekPrev(const LIST_NODE *listNode, LIST_NODE **readNode);
void * vListPeekPrev(const LIST_NODE *listNode);

/******************************************************************************
 *函数名称：  ListPeekIndex
 *输入参数：  listManage,链表管理器
 *			  index,索引，如果是负数，则表示从后向前搜索
 *输出参数：  readNode,获取的节点地址
 *返回值  ：  获取成败信息
 *功能描述：  根据索引获取节点
 ******************************************************************************/
LIST_RETURN ListPeekIndex(const LIST_MANAGE *listManage, int32_t index, LIST_NODE **readNodes);
void * vListPeekIndex(const LIST_MANAGE *listManage, int32_t index);

/******************************************************************************
 *函数名称：  ListPeekItem
 *输入参数：  listManage,链表管理器
 *			  listNode,已知节点
 *输出参数：  index,索引的地址
 *返回值  ：  获取成败信息
 *功能描述：  根据节点获取索引
 ******************************************************************************/
LIST_RETURN ListPeekItem(const LIST_MANAGE *listManage, const LIST_NODE *listNode, int32_t *index);
int32_t vListPeekItem(const LIST_MANAGE *listManage, const LIST_NODE *listNode);

/******************************************************************************
 *函数名称：  ListPutHead
 *输入参数：  listManage,链表管理器
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入到链表首位置
 ******************************************************************************/
LIST_RETURN ListPutHead(LIST_MANAGE *listManage, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListPutTail
 *输入参数：  listManage,链表管理器
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入到链表尾位置
 ******************************************************************************/
LIST_RETURN ListPutTail(LIST_MANAGE *listManage, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListInsertBeforItem
 *输入参数：  listManage,链表管理器
 *			  listNode,已知节点
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入已知节点的前边
 ******************************************************************************/
LIST_RETURN ListInsertBeforItem(LIST_MANAGE *listManage, LIST_NODE *listNode, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListInsertAfterItem
 *输入参数：  listManage,链表管理器
 *			  listNode,已知节点
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入已知节点的后边
 ******************************************************************************/
LIST_RETURN ListInsertAfterItem(LIST_MANAGE *listManage, LIST_NODE *listNode, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListInsertBeforIndex
 *输入参数：  listManage,链表管理器
 *			  index,指定索引，可以是负数
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入指定索引的前边
 ******************************************************************************/
LIST_RETURN ListInsertBeforIndex(LIST_MANAGE *listManage, int32_t index, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListInsertAfterIndex
 *输入参数：  listManage,链表管理器
 *			  index,指定索引，可以是负数
 *			  lnew,新节点
 *输出参数：  无
 *返回值  ：  获取成败信息
 *功能描述：  新节点插入指定索引的后边
 ******************************************************************************/
LIST_RETURN ListInsertAfterIndex(LIST_MANAGE *listManage, int32_t index, LIST_NODE *lnew);

/******************************************************************************
 *函数名称：  ListPopHead
 *输入参数：  listManage,链表管理器
 *输出参数：  out, 要删除的节点，若为NULL表示删除失败
 *返回值  ：  成败信息
 *功能描述：  删除首节点
 ******************************************************************************/
LIST_RETURN ListPopHead(LIST_MANAGE *listManage, LIST_NODE **out);
void *vListPopHead(LIST_MANAGE *listManage);
/******************************************************************************
 *函数名称：  ListPopEnd
 *输入参数：  listManage,链表管理器
 *输出参数：  out, 要删除的节点，若为NULL表示删除失败
 *返回值  ：  成败信息
 *功能描述：  删除尾节点
 ******************************************************************************/
LIST_RETURN ListPopEnd(LIST_MANAGE *listManage, LIST_NODE **out);
void *vListPopEnd(LIST_MANAGE *listManage);

/******************************************************************************
 *函数名称：  ListPopItem
 *输入参数：  listManage,链表管理器
 *			  listNode,要删除的节点
 *输出参数：  无
 *返回值  ：  成败信息
 *功能描述：  删除指定节点
 ******************************************************************************/
LIST_RETURN ListPopItem(LIST_MANAGE *listManage, LIST_NODE *listNode);

/******************************************************************************
 *函数名称：  ListPopIndex
 *输入参数：  listManage,链表管理器
 *			  index,要删除的节点索引，可以为负数
 *输出参数：  out, 要删除的节点，若为NULL表示删除失败
 *返回值  ：  成败信息
 *功能描述：  删除指定索引的节点
 ******************************************************************************/
LIST_RETURN ListPopIndex(LIST_MANAGE *listManage, int32_t index, LIST_NODE **out);
void *vListPopIndex(LIST_MANAGE *listManage, int32_t index);
/******************************************************************************
 *函数名称：  ListSwitchItems
 *输入参数：  listManage,链表管理器
 *			  node1、node2,要交换的两个节点
 *输出参数：  无
 *返回值  ：  成败信息
 *功能描述：  交换两个指定的节点
 ******************************************************************************/
LIST_RETURN ListSwitchItems(LIST_MANAGE *listManage, LIST_NODE *node1, LIST_NODE *node2);

/******************************************************************************
 *函数名称：  ListSwitchIndex
 *输入参数：  listManage,链表管理器
 *			  index1、index1,要交换的两个节点的索引
 *输出参数：  无
 *返回值  ：  成败信息
 *功能描述：  交换两个指定索引的节点
 ******************************************************************************/
LIST_RETURN ListSwitchIndex(LIST_MANAGE *listManage, int32_t index1,int32_t index2);

//数据比较的函数指针类型
typedef int (* FUN_COMPARE)(const LIST_NODE *, const LIST_NODE *);

/******************************************************************************
 *函数名称：  ListSort
 *输入参数：  listManage,链表管理器
 *			  s2b,从小到大排列，TRUE为从小到大，FALSE为从大到小 
 *			  fun_compare,用户编写的比较策略回调函数
 *输出参数：  无
 *返回值  ：  成败信息
 *功能描述：  链表排序
 ******************************************************************************/
LIST_RETURN ListSort(LIST_MANAGE *listManage, bool s2b, FUN_COMPARE fun_compare);

#endif

